package com.itheima.pinda.authority.biz.service.auth.impl;


import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.itheima.pinda.auth.server.utils.JwtTokenServerUtils;
import com.itheima.pinda.auth.utils.JwtUserInfo;
import com.itheima.pinda.auth.utils.Token;
import com.itheima.pinda.authority.biz.service.auth.ResourceService;
import com.itheima.pinda.authority.biz.service.auth.UserService;
import com.itheima.pinda.authority.dto.auth.LoginDTO;
import com.itheima.pinda.authority.dto.auth.ResourceQueryDTO;
import com.itheima.pinda.authority.dto.auth.UserDTO;
import com.itheima.pinda.authority.entity.auth.Resource;
import com.itheima.pinda.authority.entity.auth.User;
import com.itheima.pinda.base.R;
import com.itheima.pinda.common.constant.CacheKey;
import com.itheima.pinda.dozer.DozerUtils;
import com.itheima.pinda.exception.code.ExceptionCode;
import lombok.extern.slf4j.Slf4j;
import net.oschina.j2cache.CacheChannel;
import org.apache.commons.codec.digest.DigestUtils;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;


/**
 * @description:
 * @author: admin
 * @time: 2022/10/17 11:18
 */
@Service
@Slf4j
public class AuthManager {

    @Autowired
    private UserService userService;

    @Autowired
    private DozerUtils dozerUtils;

    @Autowired
    private JwtTokenServerUtils jwtTokenServerUtils;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private CacheChannel cacheChannel;

    public R<LoginDTO> login(String account, String password) {
        //1.校验账号密码
        R<User> check = check(account, password);
        Boolean isError = check.getIsError();
        if (isError) {
            return R.fail("认证失败");
        }


        //2.生成jwt令牌
        User user = check.getData();
        Token token = getToken(user);

        //   3.将用户权限给前端使用，进行缓存
        List<Resource> userResource = resourceService.findVisibleResource(ResourceQueryDTO
                .builder()
                .userId(user.getId())
                .build());

        List<String> permissionList = null;
        if (userResource != null && userResource.size() > 0) {
            //前端用
            permissionList = userResource
                    .stream()
                    .map(Resource::getCode)
                    .collect(Collectors.toList());


            //  4.将用户对应的权限给后端网关，进行缓存
            //缓存
            List<String> visibleResource = userResource
                    .stream()
                    .map(resource -> resource.getMethod() + resource.getUrl())
                    .collect(Collectors.toList());

            cacheChannel.set(CacheKey.USER_RESOURCE, user.getId().toString(), visibleResource);
        }
        log.info("当前用户拥有的权限:" + userResource);
        //  5.封装返回结果
        LoginDTO loginDTO = LoginDTO
                .builder()
                .user(dozerUtils.map(user, UserDTO.class))
                .permissionsList(permissionList)
                .token(token)
                .build();


        return R.success(loginDTO);


    }

    public Token getToken(User user) {
        JwtUserInfo jwtUserInfo = new JwtUserInfo(
                user.getId(),
                user.getAccount(),
                user.getName(),
                user.getOrgId(),
                user.getStationId()
        );
        return jwtTokenServerUtils.generateUserToken(jwtUserInfo, null);
    }

    /**
     * 校验账号密码
     *
     * @param account  账号
     * @param password 密码
     * @return R<User>
     */
    public R<User> check(String account, String password) {
        User user = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getAccount, account));
        String md5Hex = DigestUtils.md5Hex(password);
        if (user == null || !user.getPassword().equals(md5Hex)) {
            return R.fail(ExceptionCode.JWT_USER_INVALID);
        }
        return R.success(user);
    }
}
